/*-----------------------------------------
file name  : fxp_zoom.v
created    : 2025/04/25 15:45:58
modified   : 2025-04-25 17:56:51
description: bit width conversion for fixed-point
notes      : synthesizbale
author     : yyrwkk
-----------------------------------------*/
module fxp_zoom #(
    parameter WII  = 8      ,
    parameter WIF  = 8      ,
    parameter WOI  = 8      ,
    parameter WOF  = 8      ,
    parameter ROUND= 1      
)(
    input  [WII+WIF-1:0] in       ,
    output [WOI+WOF-1:0] out      ,
    output               overflow
);

// inr signal is used to process round mode
wire [ WII+WOF-1 : 0 ] inr  ;
wire [ WII-1     : 0 ] ini  ;
wire [ WOI-1     : 0 ] outi ;
wire [ WOF-1     : 0 ] outf ;

// round logic
generate 
if(WOF<WIF) begin
    if(ROUND==0) begin
        assign inr = in[WII+WIF-1:WIF-WOF];
    end else if(WII+WOF>=2) begin
        assign inr = (in[WIF-WOF-1] & ~(~inr[WII+WOF-1] & (&inr[WII+WOF-2:0])))
                     ?
                     in[WII+WIF-1:WIF-WOF] + 1'b1
                     :
                     in[WII+WIF-1:WIF-WOF];
    end else begin
        // assign inr = in[WII+WIF-1:WIF-WOF]; 
        assign inr = (in[WIF-WOF-1] & inr[WII+WOF-1])
                     ?
                     in[WII+WIF-1:WIF-WOF] + 1'b1
                     :
                     in[WII+WIF-1:WIF-WOF];
    end
end else if(WOF==WIF) begin
    assign inr = in; // also can merge to the next branch
end else begin
    assign inr = {in,{(WOF-WIF){1'b0}}};  
end
endgenerate

// out logic
assign ini = inr[WII+WOF-1 -: WII];
generate 
if( WOI<WII ) begin
    wire   pos_overflow;
    wire   neg_overflow;
    assign pos_overflow = (~ini[WII-1]) & ( |ini[WII-2:WOI-1]    );  
    assign neg_overflow = ( ini[WII-1]  & (~(&ini[WII-2:WOI-1])) ); 

    assign overflow = pos_overflow | neg_overflow;
    assign outf     = pos_overflow ? {WOF{1'b1}} :
                      neg_overflow ? {WOF{1'b0}} :
                      inr[WOF-1:0];
    assign outi     = pos_overflow ? { 1'b0,{(WOF-1){1'b1}} } :
                      neg_overflow ? { 1'b1,{(WOF-1){1'b0}} } :
                      ini[WOI-1:0];
end else begin
    assign overflow = 1'b0        ;
    assign outf     = inr[WOF-1:0];
    assign outi     = ( ini[WII-1] ) ?
                      { {(WOI-WII){1'b1}},ini } :
                      { {(WOI-WII){1'b0}},ini } ;
end 
endgenerate

assign out = {outi, outf};

endmodule
